package jui.model
{
	import jui.business.vo.MessageIdVO;

	public class MessageRenderer
	{
		public var cnf: Config = Config.getConfig();
		
		public static const typeLogin: String = "http://juick.com/login?";
		public static const typeLast10: String = "Last 10 messages:";
		public static const typeReplyBy: String = "Reply by ";
		public static const typeReplyPosted: String = "Reply posted.";
		public static const typeNewMessagePosted: String = "New message posted.";
		public static const typeNewMessageByUser: String = "@";

		public static const typeUserInfo: String = "Blog: http://juick.com/";
		public static const typeTopUsers: String = "Top 10 personal blogs:";
		
		//public static const typeLast10: String = "Last 10 messages:"; 
		
		private var defaultNS: Namespace = new Namespace("","jabber:client");
		private var messageNS: Namespace = new Namespace("","http://juick.com/message");
		private var streamNS: Namespace = new Namespace("stream", "http://etherx.jabber.org/streams");
		
		public var messageType: String = "";
		
		/** 
		Login:
		
		<message from='juick@juick.com/Juick' to='ok@jabber.org/31410445841247762565930884' type='chat'>
			<body>http://juick.com/login?IBOdykK7iFPqznFT</body>
		</message>
		*/
		
		/**
		New message by user:
		
		<message from='juick@juick.com/Juick' to='ok@jabber.org' type='chat'>
		<body>@Talik:
		На седьмом этаже, соседи спят уже...
		
		#187780 http://juick.com/187780</body>
		<thread>juick-187780</thread>
		<juick xmlns='http://juick.com/message' mid='187780' uid='1493' uname='Talik'>
		<body>На седьмом этаже, соседи спят уже...</body></juick>
		</message>
		*/
		
		/*
		Reply posted:
		<message from='juick@juick.com/Juick' to='ok@jabber.org/5989352031247764811600313' type='chat'>
			<body>Reply posted.
		#187808/3 http://juick.com/187808#3</body>
		</message>
		*/
		
		/**
		Reply by user:
		
		<message from='juick@juick.com/Juick' to='ok@jabber.org' type='chat'>
		<body>Reply by @Talik:
		&gt;@Talik Да, ты прав... но мне кажется, что у Ива...
		
		@OK искусственность блондинок нам навязывают &quot;страшненькие брюнетки&quot;, дескать блондинки как барби, сплош плассмасса, а я вся такая естественная хотя и страшная как смертный грех.
		
		#187808/4 http://juick.com/187808#4</body>
		
		<thread>juick-187808</thread>
		<juick xmlns='http://juick.com/message' mid='187808' replyto='3' rid='4' uid='1493' uname='Talik'>
		<body>@OK искусственность блондинок нам навязывают &quot;страшненькие брюнетки&quot;, дескать блондинки как барби, сплош плассмасса, а я вся такая естественная хотя и страшная как смертный грех.</body>
		</juick>
		</message>
		
		*/
		
		/** New message by me:
		<message from='juick@juick.com/Juick' to='ok@jabber.org/31410445841247762565930884' type='chat'>
		<body>New message posted.
		#187785 http://juick.com/187785</body>
		</message>
		*/
		
		/*
		<message 
			from='juick@juick.com/Juick' 
			to='ok@jabber.org/40675058521247760719245067' 
			type='chat'>
			<body>
				Reply posted.
				#187738/4 http://juick.com/187738#4
			</body>
		</message>
		*/
		
		/*

		<message 
			from='juick@juick.com/Juick' 
			to='ok@jabber.org/15013768561247761905726620' 
			type='chat'>
		<body>Last 10 messages:
		@blacklion:
		Мда... Очередной level 0 dump с сервера занял 5+ гиг со сжатием... В прошлоом месяце было 3+... Как бы быстро найти -- за счёт чего?!
		#187760 http://juick.com/187760
		
		@Alaija:
		Покрутил wirstball в течение получаса, руки отваливаются
		#187764 http://juick.com/187764</body>
		</message>
		*/
		
		private var _body: String = "";

		private var _xml: XML;
		private var _xmlList: XMLList;
		
		public function MessageRenderer()
		{
		}

		public function get body():String
		{
			return _body;
		}

		public function set body(value:String):void
		{
			_body = value;
			
			if(body.indexOf(typeLogin) == 0)
			{
				messageType = typeLogin;
			}
			else if(body.indexOf(typeNewMessagePosted) == 0)
			{
				messageType = typeNewMessagePosted;
			}
			else if(body.indexOf(typeNewMessageByUser) == 0)
			{
				messageType = typeNewMessageByUser;
			}
			else if(body.indexOf(typeUserInfo) == 0)
			{
				messageType = typeUserInfo;
			}
			else if(body.indexOf(typeTopUsers) == 0)
			{
				messageType = typeTopUsers;
			}
			else if(body.indexOf(typeLast10) == 0)
			{
				messageType = typeLast10;
			}
			else if (body.indexOf(typeReplyBy) == 0)
			{
				messageType = typeReplyBy;
			}
			else if (body.indexOf(typeReplyPosted) == 0)
			{
				messageType = typeReplyPosted;
			}
			
			trace ("Message type: " + messageType + ", body: " + _body );
		}

		public function toHTML(): String
		{
			var html: String = _body;
			
			switch( messageType )
			{
				case typeLogin:
				{
					html = '<u><a href="' + _body + '">Click to log in</a></u>';
					break;
				}
				case typeLast10:
				{
					/** 
					 <message from='juick@juick.com/Juick' to='ok@jabber.org/JUI' type='chat'><body>Last 10 messages:
						@test@cblp.su:
						aa
						#200426 http://juick.com/200426
						
						@Redfoxnet: *film
						
						&quot;Вы и вправду двуличная задница&quot;
						#200427 http://juick.com/200427
						
						@Shadow-Panther:
						а гет на 200000 уже?
						#200429 (1 reply) http://juick.com/200429
						
						@Scorpil:
						на хабре совсем ничего интересного =(
						#200430 http://juick.com/200430
						
						@seeker:
						блин умудрился промахнуться мимо треда а уже и ответить успели ;)
						#200431 (1 reply) http://juick.com/200431
						
						@Shadow-Panther:
						с какого-то момента жуйк перестал давать xmpp: ссылку в сообщениях. а так удобно было...
						#200432 http://juick.com/200432
						
						@zoporezka@gmail.com: *парадоксы
						атом водорода:ядро и на орбите один элетрон(учебник ф��зики и химии). Согласны? Что находится между ядром и электроном, какая среда?
						#200433 http://juick.com/200433
						
						@eill: *it *linux
						а что, swsoft openvz по gplv3 распространяет? Тут читаю конфиг от openvz, а там указано, что &quot;you may redistribute it and/or modify it under the terms of GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version&quot;. Удивлен преизрядно.
						#200434 http://juick.com/200434
						
						@stanis:
						Жуйк, я тут вопрос сочинил: http://clubs.ya.ru/4611686018427406302/replies.xml?item_no=28629 Версии?
						#200435 http://juick.com/200435
						
						@illuthion: *gmm
						Жесть...пакет googlemusicmanager собран настолько криво что apt не хочет его удалять)
						#200436 http://juick.com/200436</body></message>
						Message type: Last 10 messages:, body: Last 10 messages:
						@test@cblp.su:
						aa
						#200426 http://juick.com/200426
						
						@Redfoxnet: *film
						
						"Вы и вправду двуличная задница"
						#200427 http://juick.com/200427
						
						@Shadow-Panther:
						а гет на 200000 уже?
						#200429 (1 reply) http://juick.com/200429
						
						@Scorpil:
						на хабре совсем ничего интересного =(
						#200430 http://juick.com/200430
						
						@seeker:
						блин умудрился промахнуться мимо треда а уже и ответить успели ;)
						#200431 (1 reply) http://juick.com/200431
						
						@Shadow-Panther:
						с какого-то момента жуйк перестал давать xmpp: ссылку в сообщениях. а так удобно было...
						#200432 http://juick.com/200432
						
						@zoporezka@gmail.com: *парадоксы
						атом водорода:ядро и на орбите один элетрон(учебник физики и химии). Согласны? Что наход��тся между ядром и электроном, какая среда?
						#200433 http://juick.com/200433
						
						@eill: *it *linux
						а что, swsoft openvz по gplv3 распространяет? Тут читаю конфиг от openvz, а там указано, что "you may redistribute it and/or modify it under the terms of GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version". Удивлен преизрядно.
						#200434 http://juick.com/200434
						
						@stanis:
						Жуйк, я тут вопрос сочинил: http://clubs.ya.ru/4611686018427406302/replies.xml?item_no=28629 Версии?
						#200435 http://juick.com/200435
						
						@illuthion: *gmm
						Жесть...пакет googlemusicmanager собран настолько криво что apt не хочет его удалять)
						#200436 http://juick.com/200436 
					*/
					
					//html = htmlIze( _body );
					html = controlize( _body );
					break;
				}
				case typeNewMessagePosted:
				{
					/** 
					<body>New message posted.
					#187785 http://juick.com/187785</body>
					*/
					
					var messageIdIndexStart: int = _body.indexOf("\n#");
					var messageIdIndexEnd: int = _body.indexOf(" ", messageIdIndexStart);
					var httpLinkIndex: int = _body.indexOf("http://juick.com/", messageIdIndexEnd); 
					
					var messageHeading: String = typeNewMessagePosted;
					var messageId: String = _body.substring(messageIdIndexStart + 2, messageIdIndexEnd );
					//var messageHttpLink: String = _body.substr(httpLinkIndex); 

					var midVO: MessageIdVO = new MessageIdVO(messageId);
					
					html = '<p class="newMessagePosted">' + messageHeading +
						messageIdToControl(midVO.mid, midVO.rid, true, true, true, true) + 
						//' Web: <a href="' + messageHttpLink + '">' + messageHttpLink 
						'</a></p>';
					break;
				}
				case typeReplyPosted:
					/** 
					<body>New message posted.
					#187785 http://juick.com/187785</body>
					*/
					
					messageIdIndexStart = _body.indexOf("\n#");
					messageIdIndexEnd = _body.indexOf(" ", messageIdIndexStart);
					httpLinkIndex = _body.indexOf("http://juick.com/", messageIdIndexEnd); 
					
					messageId = _body.substring(messageIdIndexStart + 2, messageIdIndexEnd );
					//messageHttpLink = _body.substr(httpLinkIndex);
					
					midVO = new MessageIdVO(messageId);
					
					html = '<p class="newMessagePosted">Reply posted: ' +
						messageIdToControl(midVO.mid, midVO.rid, true);
					break;
				
				case typeReplyBy:
				{
					/**
					<message from='juick@juick.com/Juick' to='ok@jabber.org' type='chat'>
					<body>Reply by @Talik:
					&gt;@Talik Да, ты прав... но мне кажется, что у Ива...
					
					@OK искусственность блондинок нам навязывают.
					
					#187808/4 http://juick.com/187808#4</body>
					
					<thread>juick-187808</thread>
					<juick xmlns='http://juick.com/message' mid='187808' replyto='3' rid='4' uid='1493' uname='Talik'>
					<body>@OK искусственность блондинок нам навязывают.</body>
					</juick>
					</message>
					*/
					
					if(xml)
					{
						var messageBody: String = xml.defaultNS::body[0].text().toString();
						var j: XMLList = xml..messageNS::juick;
						
						var uname: String = j.@uname;
						var mid: String = j.@mid;
						var replyTo: String = j.@replyto;
						var rid: String = j.@rid;
						var uid: String = j.@uid;
						var replyBody: String = j.messageNS::body.text();
					}
					
					// remove Reply by @Talik:\n
					var replacePattern: RegExp = /Reply by @[a-zA-Z0-9]+:\n/g;
					var messageBodyFixed:String = messageBody.replace( replacePattern, "");
					
					// remove "\n#187808/4 http://juick.com/187808#4"
					replacePattern = /\n\#\d+\/\d+\shttp:\/\/juick.com\/\d+\#\d+/g
					messageBodyFixed = messageBodyFixed.replace( replacePattern, "");
					
					html = '<h3>Reply by @<a href="http://juick.com/' + uname + '">' + uname + '</a>:</h3> ' +
					'<p class="replyQuote">' + messageBodyFixed + '</p>' +
					
					'<p>' + messageIdToControl(mid, rid, true) + '</p>';
					
					break;
				}
				case typeNewMessageByUser:
				{
					/**
					
					* Incoming XML:
					 
					<message from='juick@juick.com/Juick' to='ok@jabber.org' type='chat'>
					<body>@soulless:
					Только что промачались две скорых с мигалками. Сдается мне, где-то было ДТП, а может еще чего
					
					#190976 http://juick.com/190976</body>
					<thread>juick-190976</thread>
					<juick xmlns='http://juick.com/message' mid='190976' uid='1915' uname='soulless'>
					<body>Только что промачались две скорых с мигалками. Сдается мне, где-то было ДТП, а может еще чего</body>
					</juick>
					<x xmlns='jabber:x:delay' stamp='20090719T10:06:00'/>
					</message>
					
					* Target render:
					
					@soulless:
					Message text
					
					#190976 http://juick.com/190976
					*/

					if(xml)
					{
						messageBody = xml.defaultNS::body[0].text().toString();
						j = xml..messageNS::juick;
						
						mid = j.@mid;
						uid = j.@uid;
						uname = j.@uname;
						var juickbody: String = j.messageNS::body.text();
						
						if( juickbody != "")
						{
							messageHeading = typeNewMessageByUser;
						
							html = '<h2>@<a href="'+cnf.juickBaseURL+uname+'">'+uname+'</a>:</h2> '+
								'<p class="replyQuote">'+juickbody+'</p>'+
								'<p>' + messageIdToControl(mid, null, false) + '</p>';
						}
						else
						{
							html = controlize(messageBody);
						}
					}
					break;
				}
				case typeUserInfo:
				{
					// Here, we will use regexp to enrich the user info text with links  
					/**
					<message from='juick@juick.com/Juick' to='flexa@jabber.org/JUI' type='chat'><body>Blog: http://juick.com/OK/
						Full name: D LAST
						From: Жуйляндия
						Web site: http://designcollector.ru/
						Status: Available
						Last messages: #191202 #191203 #191205 #191207 #191208 #191256 #191374 #191379 #191384 #191386</body></message>
					*/
					
					html = controlize(_body);
					
					//html = htmlIze(_body);
					
					break;
				}
					
				case typeTopUsers:
				{
					/*
					<message from='juick@juick.com/Juick' to='flexa@jabber.org/JUI' type='chat'><body>Top 10 personal blogs:
						
						@umputun (828 readers)
						@ugnich (703)
						@johan (243)
						@freefd (231)
						@stfoo (202)
						@StraNNicK (163)
						@alv (157)
						@aim (136)
						@konkere (114)
						@BashOrgRu (91)</body></message>
					*/
					
					html = htmlIze(_body);
					html = html.replace( /Top 10 personal blogs/g , '<h1>Top 10 personal blogs</h1>');
				}
				default:
				{
					//html = htmlIze(_body);
					html = controlize(_body);
				}
			}
			
			if(Config.getConfig().openLinksInsideJUI)
			{
				var replaceHTTP: RegExp = /http:\/\//g;
				html = html.replace(replaceHTTP, 'event:' + cnf.LINK_EVENT_OPEN_URL + ':')
			}
			
			return html;
		}

		public function get xml():XML
		{
			return _xml;
		}

		public function set xml(value:XML):void
		{
			_xml = value.copy();// new XML(value);
			_xmlList = new XMLList(_xml);
		}
		
		//----------------------------------------------------------------------
		// Message HTML-izing
		//----------------------------------------------------------------------

		private function htmlIze(text:String): String
		{
			var result: String = text;
			result = convertURLsToLinks(result);
			result = convertMessageIdsToLinks(result);
			result = convertUserIdsToLinks(result);
			
			return result;
		}		
		
		private function messageIdToWebLink(mid: String, rid: String = null): String
		{
			var ridSuffix: String = "";
			if(rid != null)
			{
				ridSuffix = "#" + rid;
			}
			
			var link: String = '<a href="' + cnf.juickBaseURL + mid + ridSuffix + '">#'
				+ mid + ridSuffix + '</a>';
			
			return link;
		}
		
		private function userIdToWebLink(uid: String): String
		{
			var link: String = '<a href="' + cnf.juickBaseURL + uid + '">@'	+ uid + '</a>';
			
			return link;
		}
		
		private function httpToWebLink(httpUrl: String = null): String
		{
			var link: String = '<a href="http://' + httpUrl + '">'	+ httpUrl + '</a>';
			
			return link;
		}		
		
		// Replace links:
		private function convertURLsToLinks(text:String): String
		{
			var regExLinks: RegExp = /http:\/\/(w{0,3}[a-zA-Z0-9_\-.:\#\/\~\}]+)/g
				return text.replace( regExLinks, httpToWebLink("$1") );
		}
		
		// Replace all latest messages with urls
		private function convertMessageIdsToLinks(text:String): String
		{
			//var regExMessageId: RegExp = /\s\#(\d+)/g;
			var regExMessageId: RegExp = /\s\#(\d+)(\/*\d)*/g;
			return text.replace( regExMessageId, " " + messageIdToWebLink("$1$2") ); 
		}
		
		// Replace all @users with urls
		private function convertUserIdsToLinks(text:String): String
		{
			var regExUserId: RegExp = /\@([a-zA-Z0-9]+)/g;
			return text.replace( regExUserId, " " + userIdToWebLink("$1") ); 
		}
		
		//----------------------------------------------------------------------
		// Message Control-izing
		//----------------------------------------------------------------------

		private function controlize(text:String): String
		{
			var result: String = text;
			
			//result = userIdToWebLink(result);
			
			result = messageIdsToControls(result);
			
			return result;
		}

		// Replace all messageIds (#231234/23) with controls
		private function messageIdsToControls(text:String): String
		{
			var regExMessageId: RegExp = /\s\#(\d+)(\/*\d)*/g;
			
			var result: String = text;
			result = result.replace( regExMessageId, 
				"\n" + messageIdToControl( "$1", "$2", true, true, true ) );
			
			/*
			// Array like: #197000, #197737, #197791, #198121, #199247 
			var arrIds: Array = text.match(regExMessageId);
			
			
			for each( var messageId: String in arrIds)
			{
				var messageIdVO: MessageIdVO = new MessageIdVO(messageId);
				
				result += "\n" + messageIdToControl( messageIdVO.mid, messageIdVO.rid, true, true, true ); 
			}
			*/
			return result; 
		}
		
		/**
		 * Transforms "12345/1" to "Reply to #12345/1 [del][read][unsub]"
		 * @param mid Message Id like: "12345" 
		 * @param rid Reply Id (optional) like: "1"
		 * @param showDeleteLink
		 * @param showReadLink
		 * @param showUnsubscribeLink
		 * @return Message Id converted to set of links like: "Reply to #12345/1 [del][read][unsub]"
		 */
		private function messageIdToControl(mid: String, rid: String = null, 
											showDeleteLink: Boolean = false, 
											showReadLink: Boolean = true,
											showUnsubscribeLink: Boolean = true,
											showSubscribeLink: Boolean = true
		): String
		{
			var webLink: String = "";
			var replyLink: String = "";
			var deleteLink: String = "";
			var readLink: String = "";
			var unsubscribeLink: String = "";
			var subscribeLink: String = "";
			
			var result: String = "";
			
			var ridSuffix: String = "";
			var ridSuffixForWeb: String = "";
			if(rid != null && rid != "" && !isNaN(parseInt(rid)))
			{
				ridSuffix = '/' + rid;
				ridSuffixForWeb = '#' + rid;
			}
			
			replyLink = '<a href="event:' + cnf.LINK_EVENT_REPLY_TO + ':' + mid + ridSuffix + '">Reply to #' + mid + ridSuffix + '</a>';
			
			if(showDeleteLink)
			{
				deleteLink = ' <a href="event:' + cnf.LINK_EVENT_DELETE_MESSAGE_BY_ID + ':' + mid + ridSuffix + '">[del]</a>';
			}
			if(showReadLink)
			{
				readLink = ' <a href="event:' + cnf.LINK_EVENT_READ_MESSAGE_BY_ID + ':' + mid + ridSuffix + '">[read]</a>';
			}
			if(showUnsubscribeLink)
			{
				unsubscribeLink = ' <a href="event:' + cnf.LINK_EVENT_UNSUBSRIBE_FROM_MESSAGE_BY_ID + ':' + mid + '">[unsub]</a>';
			}
			
			if(showSubscribeLink)
			{
				subscribeLink = ' <a href="event:' + cnf.LINK_EVENT_SUBSCRIBE_TO_MESSAGE_BY_ID + ':' + mid + '">[sub]</a>';
			}
			
			webLink = ' Web: <a href="' + cnf.juickBaseURL + mid + ridSuffixForWeb + '">' + cnf.juickBaseURL + mid + ridSuffixForWeb + '</a>';
			
			result = replyLink + deleteLink + readLink + unsubscribeLink + subscribeLink + webLink;  
			
			return result
		}
		
		//----------------------------------------------------------------------
		// Utilities
		//----------------------------------------------------------------------
		
		/**
		 * Converts message id like " #12345/6" to typed MessageID Value object with properties mid and rid    
		 * @param messageId String, like " #12345/6", "#12345" or "12345/6"
		 * @return MessageIdVO, a typed object with parsed message ID (mid) and reply ID (rid)   
		 * 
		 */
		private function parseMessageId(messageId: String): MessageIdVO
		{
			var messageIdVO: MessageIdVO = new MessageIdVO(messageId);
			
			return messageIdVO;
		}
	}
}